home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d22 / splitc.arc / SPLIT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1988-04-14  |  8.8 KB  |  210 lines

  1. /* Here we have SPLIT.C written for the Turbo C compiler.  While it was written
  2.  * using Tubro C version 1.5 it will compile under version 1.0 and with only a
  3.  * slight modification also under Microsoft C ver 5.0 and QuickC ver 1.0.  To
  4.  * have the program compile under MSC 5.0 all you need do is insert another
  5.  * include directive:  #include <sys\types.h> and delete the line
  6.  *
  7.  *             case EINVACC: printf("Invalid access code"); break;
  8.  *
  9.  * in the filerr() function.  With Quick C you also have to make sure that the
  10.  * fdopen() function is included in the library that you link with split.obj.
  11.  * For information on how to do this see section 10.1.3 "Standard Library
  12.  * Routines in Quick Libraries" on page 239 of the Quick C Programmer's Guide.
  13.  *
  14.  * The code was written with tab stops of size 3 and a maximum of 80 columns.
  15.  * And it is hereby given to the Public Domain by Charles Lazo III, CIS User ID
  16.  * 72210,17 (enjoy!) */
  17.  
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <io.h>
  21. #include <sys\stat.h>
  22. #include <fcntl.h>
  23. #include <errno.h>
  24. #include <string.h>
  25.  
  26. #define MAXFNAMES 31    /* maximum number of output files */
  27. #define Y 89            /* for a yes response */
  28. #define y 121            /* ditto */
  29. #define BUFSIZE 2048    /* buffer size for transfer from input to output files */
  30.  
  31. void saywhat(int problem);            /* tell user proper syntax */
  32. int parse_ratios(char *ratio);    /* parse ratio argument */
  33. void checkfile(char *fname);        /* check if file exists */
  34. int gethandle(char *fname);        /* obtains file handles for output files */
  35. void filerr(int handle, char *fname);    /* file open error handler */
  36. void splitfile(FILE *s);            /* write a split output file */
  37. void allocerr(void *ptr);            /* memory allocation error handler */
  38.  
  39. int accs;                                /* to obtain file access mode */
  40. int numoutfiles;                        /* store the number of output files */
  41. long flen[MAXFNAMES];                /* file lengths for output files */
  42. long filebytes;                        /* set to bytes written to each output file */
  43. long foff;                                /* tracks offset of pointer in input file */
  44. void *buffer;                            /* set to I/O buffer of input/output files */
  45. FILE *in_stream;                        /* pointer to input file stream */
  46.  
  47. main(int argc, char **argv) {
  48.  
  49.     int i;                                /* multipurpose loop counter */
  50.     int in_handle, out_handle;        /* store handles for input and output files */
  51.     long rationum;                        /* store for relations to ratio numbers */
  52.     long inflen;                        /* store for input file length */
  53.     FILE *stream[MAXFNAMES];        /* array of pointers to output file streams */
  54.  
  55.     if (argc == 1)                        /* no command line parameters? */
  56.         saywhat(0);                        /* that's right, give syntax and exit */
  57.  
  58.     accs = O_RDONLY | O_BINARY;            /* access mode of input file */
  59.     in_handle = open(argv[1], accs);        /* open the input file */
  60.     filerr(in_handle, argv[1]);            /* check for file open error */
  61.     in_stream = fdopen(in_handle, "r");    /* set stream of input file */
  62.  
  63.     numoutfiles = argc - 3;                    /* retain number of output files */
  64.     if (!parse_ratios(argv[argc - 1]))    /* parse the ratios argument */
  65.         saywhat(1);                                /* and send syntax if error */
  66.  
  67.     rationum = 0;                                /* initialize sum */
  68.     for (i = 0; i < numoutfiles; i++)
  69.         rationum += flen[i];                    /* sum ratio numbers */
  70.  
  71.     inflen = filelength(in_handle);        /* retain size of input file */
  72.  
  73.     if (rationum > inflen || rationum == 0)    /* sum of ratio numbers must be */
  74.         saywhat(1);                                /* no larger than infile length & != 0 */
  75.  
  76.     rationum = inflen / rationum;            /* compute base to scale up */
  77.  
  78.     for (i = 0; i < numoutfiles - 1; i++) {
  79.         flen[i] *= rationum;                    /* scale 'em up */
  80.     }
  81.  
  82.     rationum = 0;                                /* last file length gets excess */
  83.     for (i = 0; i < numoutfiles - 1; i++)
  84.         rationum += flen[i];
  85.     flen[numoutfiles - 1] = inflen - rationum;
  86.  
  87.     for (i = 1; i <= numoutfiles; i++)
  88.         checkfile(argv[i + 1]);                /* check if output files exists */
  89.  
  90.     for (i = 0; i < numoutfiles; i++) {
  91.         out_handle = gethandle(argv[i + 2]);    /* open output files and */
  92.         stream[i] = fdopen(out_handle, "w");    /* associate with streams */
  93.     }
  94.  
  95.     foff = -1L * BUFSIZE;                    /* so offset == 0 on splitfile() entry */
  96.     for (i = 0; i < numoutfiles; i++) {    /* write numoutfiles of output files */
  97.         filebytes = flen[i];                    /* get an established outfile length */
  98.         splitfile(stream[i]);                /* write an outfile */
  99.         printf("\nFinished file %s", argv[i + 2]);
  100.     }
  101. }
  102.  
  103. void saywhat(int problem) {
  104.     if (problem)
  105.         printf("\nSay what???\n");
  106.     printf("\nSyntax is     SPLIT INFILE file1 file2...fileN n1:n2...:nN");
  107.     printf("\n\n");
  108.     printf("Where the file INFILE remains unaltered, but its contents will\n");
  109.     printf("be copied into the N files:  file1, file2,..., fileN, so the DOS\n");
  110.     printf("command \"copy/b file1+file2+...+fileN total\" will yield a file\n");
  111.     printf("\"total\" identical to INFILE.  The last argument, n1:n2...:nN,\n");
  112.     printf("consists of N numbers separated by colons (no spaces allowed)\n");
  113.     printf("that represent size ratios of the N output files, i.e.,\n\n");
  114.     printf("   length(fileI) = nI * [length(INFILE) / (n1 + n2 +...+ nN)]\n");
  115.     printf("   (for all I such that 1 <= I < N).\n\n");
  116.     printf("The last output file gets any excess bytes.\n");
  117.     exit(1);
  118. }
  119.  
  120. int parse_ratios(char *ratio) {            /* returns zero if error, else nonzero */
  121.     int i;
  122.     char *ratioptr;        /* set to individual ratio numbers prior to atol() */
  123.     char *colonptr;                            /* set to colons in ratio argument */
  124.     char colon = ':';                            /* colon to find in ratio argument */
  125.     colonptr = ratio;                            /* initialize to first ratio number */
  126.     ratioptr = ratio;                            /* and set ratioptr for first atol() */
  127.     for (i = 0; i < numoutfiles; i++) {
  128.         if (i == numoutfiles - 1) {        /* no colon at end; so, special case */
  129.             flen[i] = atol(ratioptr);        /* set last file length ratio */
  130.             return(1);                            /* and return success indication */
  131.         }
  132.         colonptr = strchr(ratioptr, colon);        /* point to next colon */
  133.         if (colonptr == NULL)                /* failure if no colon in argument */
  134.             return(0);
  135.         colonptr[0] = 0;                        /* place a null at colon position */
  136.         flen[i] = atol(ratioptr);            /* convert a file length ratio number */
  137.         colonptr++;                                /* point to next number */
  138.         ratioptr = colonptr;                    /* and set ratioptr for next atol() */
  139.     }
  140. }
  141.  
  142. void checkfile(char *fname) {                /* if outfile exists prompt user */
  143.     int ch;
  144.     if (access(fname, 0) != -1) {
  145.         printf("\nFile %s exists.  Overwrite (y/n)? ", fname);
  146.         ch = getche();
  147.         if (!(ch == y || ch == Y)) {
  148.             printf("\n");
  149.             exit(1);                                /* not a 'yes' response, so abort */
  150.         }
  151.         printf("\n");
  152.     }
  153. }
  154.  
  155. int gethandle(char *fname) {
  156.     int permission, handle;
  157.     accs = O_RDWR | O_CREAT | O_TRUNC | O_BINARY;    /* create file overwriting */
  158.                                                                     /* any existing file */
  159.     permission = S_IWRITE;                            /* set attribute to read/write */
  160.     handle = open(fname, accs, permission);    /* open an output file */
  161.     filerr(handle, fname);                            /* check for file open error */
  162.     return(handle);                                    /* no error, then return handle */
  163. }
  164.  
  165. void filerr(int handle, char *fname) {
  166.     if (handle == -1) {                    /* a handle of -1 signals an error */
  167.         printf("\nFile open error:  ");
  168.         switch (errno) {                    /* external 'errno' gives type of error */
  169.             case ENOENT: printf("Path or file name not found"); break;
  170.             case EMFILE: printf("Too many open files"); break;
  171.             case EACCES: printf("Permission denied"); break;
  172.             case EINVACC: printf("Invalid access code"); break;
  173.         }
  174.         printf(" for file -> %s\n", fname);
  175.         exit(1);
  176.     }
  177. }
  178.  
  179. void splitfile(FILE *stream) {        /* this function puts infile to outfiles */
  180.     buffer = malloc(BUFSIZE);            /* begin with preassigned buffer size */
  181.     allocerr(buffer);                        /* insure successful allocation */
  182.     while (filebytes) {                    /* loop till all bytes transferred */
  183.         foff += BUFSIZE;                    /* bump input file pointer */
  184.         if (filebytes >= BUFSIZE) {                    /* bytes left >= buffer size? */
  185.             fseek(in_stream, foff, SEEK_SET);        /* yeah, move infile pointer */
  186.             fread(buffer, BUFSIZE, 1, in_stream);    /* get bytes to buffer */
  187.             fwrite(buffer, BUFSIZE, 1, stream);        /* then write them to outfile */
  188.             filebytes -= BUFSIZE;                        /* reduce byte count */
  189.         }
  190.         else {                                                /* deal with remainder */
  191.             free(buffer);                                    /* release large buffer */
  192.             buffer = malloc(filebytes);                /* and make smaller one */
  193.             allocerr(buffer);                                /* check for error */
  194.             fseek(in_stream, foff, SEEK_SET);        /*    set infile pointer */
  195.             fread(buffer, filebytes, 1, in_stream);/* infile bytes to buffer */
  196.             fwrite(buffer, filebytes, 1, stream);    /* write bytes to outfile */
  197.             foff = foff + filebytes - BUFSIZE;        /* set for next outfile */
  198.             free(buffer);                                    /* free memory for next time */
  199.             filebytes = 0;                                    /* for exit of while */
  200.         }
  201.     }
  202. }
  203.  
  204. void allocerr(void *ptr) {            /* send message and abort if memory error */
  205.     if (ptr == NULL) {
  206.         printf("\nCan't allocate needed memory.\n");
  207.         exit(1);
  208.     }
  209. }
  210.